﻿using Sgr.Utilities;

namespace Sgr.Licence.Services
{
    /// <summary>
    /// 许可证管理类，负责注册与授权周期的校验
    /// </summary>
    public class AppLicenseManage : IAppLicenseManage
    {
        /// <summary>
        /// 当前许可证状态
        /// </summary>
        public LicenseStatus CurrentStatus { get; private set; } = LicenseStatus.NotActivated;

        #region 私有字段

        private string? _registrationCode;
        private readonly object _lockObject = new();
        private volatile bool _isRegistered;

        private DateTime _lastCheckRegistered = DateTime.MinValue;         // 最近一次重新加载激活信息的时间（UTC）
        private DateTime _productLastVisitDate = DateTime.MinValue;        // 最近一次成功访问的时间（UTC）
        private DateTime _startTime = DateTime.MaxValue;                   // 授权开始（UTC）
        private DateTime _endTime = DateTime.MinValue;                     // 授权结束（UTC）
        private const double TimeRollbackToleranceHours = 2d;              // 判定时间回拨的容忍阈值

        #endregion 私有字段

        #region 构造函数

        public AppLicenseManage()
        {
            // 尝试初始化（忽略异常）
            try { ValidateLicense(out _); } catch { }
        }

        #endregion 构造函数

        #region 公共方法

        /// <summary>
        /// 获取本机注册码（缓存）
        /// </summary>
        public string GetRegistrationCode()
        {
            if (!string.IsNullOrEmpty(_registrationCode))
                return _registrationCode;

            lock (_lockObject)
            {
                if (!string.IsNullOrEmpty(_registrationCode))
                    return _registrationCode;

                try
                {
                    _registrationCode = LicenseHelper.GenerateRegistrationCode();
                }
                catch
                {
#if DEBUG
                    System.Diagnostics.Debug.WriteLine("Registration code generation failed.");
#endif
                    _registrationCode = string.Empty;
                }
                return _registrationCode;
            }
        }

        /// <summary>
        /// 注册激活信息
        /// </summary>
        public bool Register(string registrationCode, string activationCode, out string message)
        {
            message = string.Empty;

            try
            {
                var activationInfo = LicenseHelper.ParseActivationCode(activationCode);
                if (activationInfo == null)
                {
                    message = "激活码格式错误";
                    return false;
                }

                // 校验匹配
                var (isValid, msg, info) = LicenseHelper.ValidateActivationInfo(activationInfo, registrationCode);
                if (!isValid || info == null)
                {
                    message = msg;
                    return false;
                }

                // 保存并立即更新内存（无需失效后再懒加载）
                LicenseHelper.SaveLicenseFile(activationCode);
                UpdateLicenseInfo(info);
                RefreshLastVisitDate();

                return true;
            }
            catch
            {
                message = "激活码错误或已到期";
                return false;
            }
        }

        /// <summary>
        /// 验证当前授权状态
        /// </summary>
        public bool ValidateLicense(out string message)
        {
            if (!IsRegisteredInternal())
            {
                CurrentStatus = LicenseStatus.NotActivated;
                message = CurrentStatus.GetDescription();
                return false;
            }

            RefreshLastVisitDate();

            var nowUtc = DateTime.UtcNow;

            if (DetectTimeRollback(nowUtc))
            {
                CurrentStatus = LicenseStatus.TimeTempered;
                message = CurrentStatus.GetDescription();
                return false;
            }

            if (nowUtc < _startTime || nowUtc > _endTime)
            {
                CurrentStatus = LicenseStatus.Expired;
                message = $"授权期限为{_startTime:yyyy-MM-dd}至{_endTime:yyyy-MM-dd}，{CurrentStatus.GetDescription()}";
                return false;
            }

            var remainingDays = Math.Ceiling((_endTime - nowUtc).TotalDays);
            if (remainingDays <= LicenseConstants.LicenseWarningDays)
            {
                CurrentStatus = LicenseStatus.NearExpiration;
                message = $"授权仅剩{remainingDays}天，请及时续费以免影响使用！";
                return true;
            }

            CurrentStatus = LicenseStatus.Valid;
            message = string.Empty;
            return true;
        }

        #endregion 公共方法

        #region 私有方法

        private bool IsRegisteredInternal()
        {
            if (_isRegistered && !IsCacheExpired())
                return true;

            lock (_lockObject)
            {
                if (_isRegistered && !IsCacheExpired())
                    return true;

                try
                {
                    var content = LicenseHelper.ReadLicenseFile();
                    if (string.IsNullOrEmpty(content))
                        return false;

                    var info = LicenseHelper.ParseActivationCode(content);
                    if (info == null)
                        return false;

                    var (valid, _, checkedInfo) = LicenseHelper.ValidateActivationInfo(info, GetRegistrationCode());
                    if (!valid || checkedInfo == null)
                        return false;

                    UpdateLicenseInfo(checkedInfo);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
        }

        private bool IsCacheExpired()
            => (DateTime.UtcNow - _lastCheckRegistered).TotalHours > LicenseConstants.CacheExpiryHours;

        private void UpdateLicenseInfo(ActivationInfo info)
        {
            // 统一补 UTC Kind（不转换绝对值，仅保证 Kind=Utc）
            _startTime = info.StartTime.EnsureUtc();
            _endTime = info.EndTime.EnsureUtc();
            _lastCheckRegistered = DateTime.UtcNow;
            _isRegistered = true;
        }

        private void RefreshLastVisitDate()
        {
            var now = DateTime.UtcNow;
            if ((now - _productLastVisitDate).TotalHours <= LicenseConstants.RefreshIntervalHours)
                return;

            try
            {
                var path = Path.Combine(LocalFileHelper.GetApplicationDirectory(), LicenseConstants.TempFileName);
                UpdateLastVisitDate(now, path);
            }
            catch
            {
#if DEBUG
                System.Diagnostics.Debug.WriteLine("RefreshLastVisitDate failed.");
#endif
            }
        }

        private void UpdateLastVisitDate(DateTime now, string tempFilePath)
        {
            var spanSeconds = (int)(now - LicenseConstants.BenchmarkDate).TotalSeconds;
            if (spanSeconds < 0) spanSeconds = 0;

            File.WriteAllText(tempFilePath, spanSeconds.ToString());
            _productLastVisitDate = now;
        }

        private bool DetectTimeRollback(DateTime currentUtc)
        {
            if (currentUtc >= _productLastVisitDate)
                return false;

            var rollbackHours = (_productLastVisitDate - currentUtc).TotalHours;
            if (rollbackHours > TimeRollbackToleranceHours)
                return true;

            return _productLastVisitDate < _startTime || _productLastVisitDate > _endTime;
        }

        #endregion 私有方法
    }
}